from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.template import TemplateDoesNotExist
from django.views.generic.simple import direct_to_template #about_pages view
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
#from forms import ReactionForm #for add_rea view, then reactionform should be defined in forms.py, can also be here
from ehmn.models import *
from settings import MEDIA_ROOT
from django import forms
from django.db.models import Q
import networkx as nx
import pydot

#dis_res=[]
#dit_res=[]

def readetail(request, reactionid):
   rea=Reaction.objects.get(reactionid=reactionid)
#   rea=Reaction.objects.select_related(depth=1).get(reactionid=reactionid)
#   genes=rea.rea_gene_set.all()
   enzymes=rea.rea_ec_set.all()
   genes= Gene.objects.filter(rea_gene__reaction__reactionid=reactionid).distinct()
   return render_to_response("rea_detail.html", locals())

def genedetail(request, gid):
   gene=Gene.objects.get(geneid=gid)
   omim=gene.omim.split(";")
   uniprot=gene.uniprot.split(";")
   locations=gene.geneloc_set.all()
   morbid=Morbid.objects.filter(gene__geneid=gid)
   dis_target=Dis_target.objects.filter(gene__geneid=gid)
   drugs=Drug_target.objects.filter(gene__geneid=gid)
   return render_to_response("gene_detail.html", locals())

def showpath(request, pname):
   reaction_list=Reaction.objects.filter(pathway__name__icontains=pname)
   return render_to_response("reaction_list.html", locals())
'''
def showpgraph(request, pname): #replaced by serving images directly use apache
   image=open("c:/human/maps/"+pname+".png","rb").read()
#   image=open(pname+".png","rb").read()
   return HttpResponse(image, mimetype="image/png")
'''
def showglobalnet(request):
  import pydot
  colors=[]
  for i in range(1,72):
   s3=str((i % 5)/4.0)
   s2=i/5
   if s2>4:
      s1=str(s2/5/2.0)
      s2=str((s2 %5)/4.0)
   else:
      if i==4:
         s3="0.000" #replace white with black
      s1="0.000"
      s2=str(s2/4.0)
   colors.append(s1+" "+s2+" "+s3)
  metlink_list=Met_link.objects.all()
  G = pydot.Dot()
  for link in metlink_list:
              e=pydot.Edge(link.com1.name,link.com2.name,arrowhead="none",tooltip=link.rea.equation,URL='/reaction/'+link.rea.reactionid)
              G.add_edge(e)
              n=pydot.Node(link.com1.name,label="",color=colors[link.pathway.pathid],tooltip=link.com1.name,URL="/compound/"+link.com1.compoundid)
              G.add_node(n)
              n=pydot.Node(link.com2.name,label="",color=colors[link.pathway.pathid],tooltip=link.com2.name,URL="/compound/"+link.com2.compoundid)
              G.add_node(n)
#  G.set_simplify("true")
  G.write(MEDIA_ROOT+'globaldot.svg', prog='dot',format='svg')
  image=open(MEDIA_ROOT+'globaldot.svg',"rb").read()
  return HttpResponse(image, mimetype="image/svg+xml")

def showSBML(request, pname):
   import libsbml as ls
   rea_list=Reaction.objects.filter(pathway__name=pname)
   spes=[] #save species names in a list for getting a list without repeat
   doc=ls.SBMLDocument(2,1) #version 2 level 3
   m=doc.createModel() #directly give an Id than not necessary to setName
#   m.setId(pname)
#   a=str('xxx')
   pname=str(pname)
   m.setName(pname)   
   cp=m.createCompartment()
   cp.setId("compartment")
   cp.setName(cp.getId())
   cp.setSize(1)
   i=1
   for rea in rea_list:
    if not 'n' in rea.eq_in_id:  #avoid polymer reactions
      r=m.createReaction() #can not use createReaction(rea[0])
      r.setId("r"+str(i))
      i=i+1
      r.setName(str(rea.reactionid))
      r.setReversible(rea.reversibility=='T') 
      a=rea.eq_in_id.split('=')
      subs=a[0].split('+')
      for sub in subs:
#        sub.strip() #trim spaces after or before the string
        b=sub.split(' ') #coefficient and compound ID seperated by space
        if len(b)==1:
          if len(b[0])>6: #some may have no white space between coeff and id
            k=b[0].find('C')
            sto=float(b[0][:k])
            species=str(b[0][k:])
          else:  
            sto=1.0
            species=str(b[0])
        else:
            sto=float(b[0])
            species=str(b[1])
        sr=r.createReactant() #create a new SpeciesReference object and add as a reactant
        sr.setStoichiometry(sto) # f is a float value
        sr.setSpecies(species) #a string as a species in Model's ListOfSpecies.
        if not species in spes:
            spes.append(species)
            s=m.createSpecies()
            s.setId(species)
            try:
               com=Compound.objects.get(compoundid=species)
               s.setName(str(com.name))
            except:
               s.setName(species)
            s.setCompartment(cp.getId()) #s is a string for compartment
#            s.setConstant(0) #0 represent false
#            s.setInitialConcentration(0.1)
      pros=a[1].split('+')
      for pro in pros:
#        pro.strip()
        b=pro.split(' ')
        if len(b)==1:
          if len(b[0])>6: #some may have no white space between coeff and id
            k=b[0].find('C')
            sto=float(b[0][:k])
            species=str(b[0][k:])
          else:  
            sto=1.0
            species=str(b[0])
        else:
            sto=float(b[0])
            species=str(b[1])
        sr=r.createProduct() #create a new SpeciesReference object and add as a reactant
        sr.setStoichiometry(sto) # f is a float value
        sr.setSpecies(species) #a string as a species in Model's ListOfSpecies.
        if not species in spes:
            spes.append(species)
            s=m.createSpecies()
            s.setId(species)
            try:
               com=Compound.objects.get(compoundid=species)
               s.setName(str(com.name))
            except:
               s.setName(species)
            s.setCompartment(cp.getId()) #s is a string for compartment
#            s.setConstant(0) #0 represent false
#            s.setInitialConcentration(0.1)
#   ls.writeSBML(doc,pname+".xml")
#   sbml=open(pname+".xml","rb").read()
   sbml=ls.writeSBMLToString(doc) #not write file on the server
   response=HttpResponse(sbml, mimetype="text/xml")
   response['Content-Disposition']='attachment; filename='+pname+'.xml'
   return response

def showpathloc(request, pname,loname):
#  import pydot
  metlink_list=Met_link.objects.filter(pathway__name=pname,rea__rea_gene__gene__geneloc__loc__abs=loname).distinct()
  G = pydot.Dot()
  for link in metlink_list:
              e=pydot.Edge(link.com1.name,link.com2.name,label=link.rea.reactionid,URL='/reaction/'+link.rea.reactionid)
              e.set_URL('/reaction/'+link.rea.reactionid)
              G.add_edge(e)
              n=pydot.Node(link.com1.name,URL="/compound/"+link.com1.compoundid)
              G.add_node(n)
              n=pydot.Node(link.com2.name,URL="/compound/"+link.com2.compoundid)
              G.add_node(n)
  G.write(MEDIA_ROOT+pname+loname+'.svg', prog='dot',format='svg')
  image=open(MEDIA_ROOT+pname+loname+".svg","rb").read()
  return HttpResponse(image, mimetype="image/svg+xml")

def showpathloc2(request, pname,loname):
#  import pydot
  metlink_list=Met_link.objects.filter(pathway__name=pname,rea__realoc__loc__abs=loname).distinct()
  G = pydot.Dot()
  for link in metlink_list:
              e=pydot.Edge(link.com1.name,link.com2.name,label=link.rea.reactionid,URL='/reaction/'+link.rea.reactionid)
              e.set_URL('/reaction/'+link.rea.reactionid)
              G.add_edge(e)
              n=pydot.Node(link.com1.name,URL="/compound/"+link.com1.compoundid)
              G.add_node(n)
              n=pydot.Node(link.com2.name,URL="/compound/"+link.com2.compoundid)
              G.add_node(n)
  G.write(MEDIA_ROOT+pname+loname+'.svg', prog='dot',format='svg')
  image=open(MEDIA_ROOT+pname+loname+".svg","rb").read()
  return HttpResponse(image, mimetype="image/svg+xml")

def showpathsvg(request, pname):
#  import pydot
  metlink_list=Met_link.objects.filter(pathway__name=pname)
  G = pydot.Dot()
  for link in metlink_list:
              e=pydot.Edge(link.com1.name,link.com2.name,label=link.rea.reactionid,URL='/reaction/'+link.rea.reactionid)
              e.set_URL('/reaction/'+link.rea.reactionid)
              G.add_edge(e)
              n=pydot.Node(link.com1.name,URL="/compound/"+link.com1.compoundid)
              G.add_node(n)
              n=pydot.Node(link.com2.name,URL="/compound/"+link.com2.compoundid)
              G.add_node(n)
  G.write(MEDIA_ROOT+pname+'.svg', prog='dot',format='svg')
  image=open(MEDIA_ROOT+pname+".svg","rb").read()
  return HttpResponse(image, mimetype="image/svg+xml")

def goviewrea(request, go):
# Visualize GO terms on network map
#  import networkx as nx
  G=nx.read_edgelist("c:/human/gograph1.txt",create_using=nx.XDiGraph())
  a=nx.single_source_shortest_path_length(G,go,cutoff=None)
  c=a.keys()
  reaction_list=Reaction.objects.filter(rea_gene__gene__gene_go__go__in=c).distinct()     
  return render_to_response('reaction_list.html', locals())

def goviewgene(request, go):
# Visualize GO terms on network map
#  import networkx as nx
  G=nx.read_edgelist(MEDIA_ROOT+'gograph1.txt',create_using=nx.XDiGraph())
  a=nx.single_source_shortest_path_length(G,go,cutoff=None)
  c=a.keys()
  gene_list=Gene.objects.filter(gene_go__go__in=c).distinct()     
  return render_to_response('gene_list.html', locals())

class pathviewform(forms.Form):
    foptions=[('jpg','jpg'),('png','png'),('gif','gif'),('svg','svg')]
#    foptions=[('jpg','jpg'),('png','png'),('gif','gif'),('bmp','bmp'),('svg','svg'),
#              ('dot','dot'),('eps','eps'),('ps','ps'),('pdf','pdf')]
    poptions=[('dot','dot'),('neato','neato'),('twopi','twopi'),('fdp','fdp')]
    fformat=forms.ChoiceField(label="format", choices=foptions,required=False)
    prog=forms.ChoiceField(label="program", choices=poptions,required=False)
    rlabel=forms.BooleanField(label="reaction label",required=False)
    mlabel=forms.BooleanField(label="metabolite label",required=False)

def showpathgraph(request, pname):
#   import networkx as nx
#   import pydot
   metlink_list=Met_link.objects.filter(pathway__name=pname)
#   el=[]
   s=''
   G = pydot.Dot()
   if request.method == 'GET':
        f = pathviewform(request.GET)
        if not f.is_valid():
           return render_to_response('dotview.html', {'form': f,'pname':'wrong'}) #do sth else 
        else:
           if f.cleaned_data["fformat"]:
              fformat=f.cleaned_data["fformat"]
           else:   
              fformat='jpg'
#              fformat='svg'
           if f.cleaned_data["prog"]:
              prog=f.cleaned_data["prog"]
           else:   
              prog='dot'
           for link in metlink_list:
#     el.append((link.com1.compoundid,link.com2.compoundid, link.rea.reactionid))
#     el.append((link.com1.name,link.com2.name, link.rea.reactionid))
#   G=pydot.graph_from_edges(el)
#method 2 with reaction label
              e=pydot.Edge(link.com1.name,link.com2.name)
              if f.cleaned_data["rlabel"]:
                 e.set_label(link.rea.reactionid)
#              e.set_label(link.rea.reactionid)
              e.set_URL('/reaction/'+link.rea.reactionid)
#     e.set_URL('/admin/ehmn/reaction/'+link.rea.reactionid)
              if link.rea.reactionid[1]=='E':
#     if link.rea in search1.objs:
                 e.set_color('red')
                 e.set_style("setlinewidth(3)")
              G.add_edge(e)
           if not f.cleaned_data["mlabel"]:
#              nlist=G.get_node_list()
#              for node in nlist:
#                 node.set_label("") #not change at all
#              G.write('media/'+pname+'.dot', prog=None, format='dot')
#              dotf=open('media/'+pname+'.dot', 'r')
#              s=dotf.read()
#              dotf.close()
              s=G.to_string()
              p=s.find('{')
#              s=s[0:p+16]+s[p+18:]
              dotf=open(MEDIA_ROOT+pname+'.dot', 'w')
              dotf.write(s[0:p+1])
              dotf.write('node [label=\"\\N\"];')
              nlist=G.get_node_list()
              for node in nlist:
#                 node.set_label("") #not change at all
                 dotf.write(node.get_name())
              dotf.write(s[p+2:])
              dotf.close()
              G=pydot.graph_from_dot_file(MEDIA_ROOT+pname+'.dot')
#              s=s.replace("\N","")
#              G=pydot.graph_from_dot_data(G.to_string()) #this function does not work,read file is ok
           G.write(MEDIA_ROOT+pname+'.'+fformat, prog=prog,format=fformat)
           if fformat=='svg':
              image=open(MEDIA_ROOT+pname+".svg","rb").read()
              return HttpResponse(image, mimetype="image/svg+xml")
           else: 
              return render_to_response("dotview.html", {'form': f,'s':s,'format': fformat,'pname':pname})
#     G.write('media/'+pname+'.dot', prog=None, format='raw')
#   G=pydot.graph_from_dot_file('1.dot')
#   return HttpResponse(image, mimetype="image/svg+xml")
#   return HttpResponse(image, mimetype="image/jpg")
#   G.write_imap(pname+'.map', prog='dot')
#write to dot before layout, then add node [label=""] in dot file to hide label;

class searchform(forms.Form):
    se_options=[('rea','reaction ID'),('com','compound ID or name'),('entrez','entrez gene ID or name'),
    ('hgen','HGNC or Ensembl ID'),('uniprot','Uniprot ID'),('ec','EC number'),('dig','genes related with disease'),
    ('dita','taget for disease'), ('drug','targeted by drug')]
    sefor_options=[('rea','reactions'),('com','compounds'),('gene','genes')]
    plist=Pathway.objects.all()
    p_options=[(0,'all')]
    for a in plist:
       p_options.append(((a.pathid),(a.name)))
#    lolist=Location.objects.all()
    loptions=[(0,'all'),(1,'extracellular'),(2,'uncertain'),(5,'nucleus'),(6,'cytosol'),
              (7,'endoplasmic reticulum'),(9,'Golgi apparatus'),(10,'peroxisomes'),
              (11,'lysosomes'),(12,'mitochondria')]
#    for a in lolist:
#       loptions.append(((a.id),(a.des)))
    se=forms.ChoiceField(label="Search by", choices=se_options,required=False)
    sefor=forms.ChoiceField(label="for", choices=sefor_options,initial='rea')
    seterm=forms.CharField(label="matching", required=False)
    pa=forms.MultipleChoiceField(label="select pathways", choices=p_options, initial=0,required=False)
    lo=forms.MultipleChoiceField(label="subcellular location", choices=loptions,initial=0,required=False)
#    pa=forms.ChoiceField(label="select pathways", widget=forms.SelectMultiple, choices=p_options)

@login_required
def search1(request):
    if request.method == 'GET':
        f = searchform(request.GET)
        if not f.is_valid():
           return render_to_response('search1.html', {'form': f}) #do sth else 
        else:
           if f.cleaned_data["sefor"]:
             if f.cleaned_data["sefor"]=='rea':
                if f.cleaned_data["seterm"]:
                  if f.cleaned_data["se"]=='rea':
                    objs = Reaction.objects.filter(reactionid__icontains=f.cleaned_data["seterm"])
                  if f.cleaned_data["se"]=='com':
                    qset = (
                      Q(equation__icontains=f.cleaned_data["seterm"]) |
                      Q(eq_in_id__icontains=f.cleaned_data["seterm"]) 
                    )
                    objs = Reaction.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='entrez':
                    qset = (
                      Q(rea_gene__gene__name=f.cleaned_data["seterm"]) |
                      Q(rea_gene__gene__geneid=f.cleaned_data["seterm"]) 
                    )
                    objs = Reaction.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='hgen':
                    qset = (
                      Q(rea_gene__gene__hgnc=f.cleaned_data["seterm"]) |
                      Q(rea_gene__gene__ensembl=f.cleaned_data["seterm"]) 
                    )
                    objs = Reaction.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='uniprot':
                    qset = (
                      Q(rea_gene__gene__uniprot__icontains=f.cleaned_data["seterm"]) |
                      Q(rea_gene__gene__altprotein__icontains=f.cleaned_data["seterm"]) 
                    )
                    objs = Reaction.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='ec':
                    objs = Reaction.objects.filter(rea_ec__enzyme=f.cleaned_data["seterm"]).distinct()
                  if f.cleaned_data["se"]=='dig':
                    objs = Reaction.objects.filter(rea_gene__gene__morbid__disorder__icontains=f.cleaned_data["seterm"]).distinct()
#                    global dis_res
#                    dis_res=[]
#                    for res in objs.values('reactionid'):
#                      dis_res.append(res['reactionid'])
                  if f.cleaned_data["se"]=='dita':
                    objs = Reaction.objects.filter(rea_gene__gene__dis_target__disease__icontains=f.cleaned_data["seterm"]).distinct()
#                    global dit_res
#                    dit_res=[]
#                    for res in objs.values('reactionid'):
#                      dit_res.append(res['reactionid'])
                  if f.cleaned_data["se"]=='drug':
                    objs = Reaction.objects.filter(rea_gene__gene__drug_target__drug__icontains=f.cleaned_data["seterm"]).distinct()
                else:
                  objs=Reaction.objects.all()
                if f.cleaned_data["pa"]:
                  if not f.cleaned_data["pa"][0][0]=='0':
                    objs=objs.filter(pathway__in=f.cleaned_data["pa"]).distinct()     
                if f.cleaned_data["lo"]:
                  if not f.cleaned_data["lo"][0][0]=='0':
                    objs=objs.filter(realoc__loc__in=f.cleaned_data["lo"]).distinct()     
#                return render_to_response('search1.html', {'form': f, 'reactions': objs, 'nre': nre})
                request.session['ehmnr']=objs
#                return render_to_response('krea.html', {'reaction_list': objs})
                return render_to_response('reaction_list.html', {'reaction_list': objs})
             if f.cleaned_data["sefor"]=='com':
                if f.cleaned_data["seterm"]:
                  if f.cleaned_data["se"]=='rea':
                    objs = Compound.objects.filter(rea_comp__reaction__reactionid__icontains=f.cleaned_data["seterm"]).distinct()
                  if f.cleaned_data["se"]=='com':
                    qset = (
                      Q(name__icontains=f.cleaned_data["seterm"]) |
                      Q(compoundid__icontains=f.cleaned_data["seterm"]) 
                    )
                    objs = Compound.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='entrez':
                    qset = (
                      Q(rea_comp__reaction__rea_gene__gene__name=f.cleaned_data["seterm"]) |
                      Q(rea_comp__reaction__rea_gene__gene__geneid=f.cleaned_data["seterm"]) 
                    )
                    objs = Compound.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='hgen':
                    qset = (
                      Q(rea_comp__reaction__rea_gene__gene__hgnc=f.cleaned_data["seterm"]) |
                      Q(rea_comp__reaction__rea_gene__gene__ensembl=f.cleaned_data["seterm"]) 
                    )
                    objs = Compound.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='uniprot':
                    qset = (
                      Q(rea_comp__reaction__rea_gene__gene__uniprot__icontains=f.cleaned_data["seterm"]) |
                      Q(rea_comp__reaction__rea_gene__gene__altprotein__icontains=f.cleaned_data["seterm"]) 
                    )
                    objs = Compound.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='ec':
                    objs = Compound.objects.filter(rea_comp__reaction__rea_ec__enzyme=f.cleaned_data["seterm"]).distinct()
                  if f.cleaned_data["se"]=='dig':
                    objs = Compound.objects.filter(rea_comp__reaction__rea_gene__gene__morbid__disorder__icontains=f.cleaned_data["seterm"]).distinct()
                  if f.cleaned_data["se"]=='dita':
                    objs = Compound.objects.filter(rea_comp__reaction__rea_gene__gene__dis_target__disease__icontains=f.cleaned_data["seterm"]).distinct()
                  if f.cleaned_data["se"]=='drug':
                    objs = Compound.objects.filter(rea_comp__reaction__rea_gene__gene__drug_target__drug__icontains=f.cleaned_data["seterm"]).distinct()
                else:
                  objs=Compound.objects.all()
                if f.cleaned_data["pa"]:
                  if not f.cleaned_data["pa"][0][0]=='0':
                    objs=objs.filter(rea_comp__reaction__pathway__in=f.cleaned_data["pa"]).distinct()     
                if f.cleaned_data["lo"]:
                  if not f.cleaned_data["lo"][0][0]=='0':
                    objs=objs.filter(rea_comp__reaction__realoc__loc__in=f.cleaned_data["lo"]).distinct()     
                return render_to_response('compound_list.html', {'compound_list': objs})
             if f.cleaned_data["sefor"]=='gene':
                if f.cleaned_data["seterm"]:
                  if f.cleaned_data["se"]=='rea':
                    objs = Gene.objects.filter(rea_gene__reaction__reactionid__icontains=f.cleaned_data["seterm"]).distinct()
                  if f.cleaned_data["se"]=='com':
                    qset = (
                      Q(rea_gene__reaction__rea_comp__compound__name__icontains=f.cleaned_data["seterm"]) |
                      Q(rea_gene__reaction__rea_comp__compound__compoundid__icontains=f.cleaned_data["seterm"]) 
                    )
                    objs = Gene.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='entrez':
                    qset = (
                      Q(name=f.cleaned_data["seterm"]) |
                      Q(geneid=f.cleaned_data["seterm"]) 
                    )
                    objs = Gene.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='hgen':
                    qset = (
                      Q(hgnc=f.cleaned_data["seterm"]) |
                      Q(ensembl=f.cleaned_data["seterm"]) 
                    )
                    objs = Gene.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='uniprot':
                    qset = (
                      Q(uniprot__icontains=f.cleaned_data["seterm"]) |
                      Q(altprotein__icontains=f.cleaned_data["seterm"]) 
                    )
                    objs = Gene.objects.filter(qset).distinct()
                  if f.cleaned_data["se"]=='ec':
                    objs = Gene.objects.filter(rea_gene__reaction__rea_ec__enzyme=f.cleaned_data["seterm"]).distinct()
                  if f.cleaned_data["se"]=='dig':
                    objs = Gene.objects.filter(morbid__disorder__icontains=f.cleaned_data["seterm"]).distinct()
                  if f.cleaned_data["se"]=='dita':
                    objs = Gene.objects.filter(dis_target__disease__icontains=f.cleaned_data["seterm"]).distinct()
                  if f.cleaned_data["se"]=='drug':
                    objs = Gene.objects.filter(drug_target__drug__icontains=f.cleaned_data["seterm"]).distinct()
                else:
                  objs=Gene.objects.all()
                if f.cleaned_data["pa"]:
                  if not f.cleaned_data["pa"][0][0]=='0':
                    objs=objs.filter(rea_gene__reaction__pathway__in=f.cleaned_data["pa"]).distinct()     
                if f.cleaned_data["lo"]:
                  if not f.cleaned_data["lo"][0][0]=='0':
                    objs=objs.filter(geneloc__loc__in=f.cleaned_data["lo"]).distinct()     
                return render_to_response('gene_list.html', {'gene_list': objs})
    else:
        f = searchform()
        return render_to_response('search1.html', {'form': f})

class humapform(forms.Form):
    se_options=[('entrez','Entrez gene ID'),('name','name'),('hgnc','HGNC ID'),('ensembl','Ensembl ID'),('omim','OMIM'),
                ('unigene','Unigene'),('gi','GenBank GI'),('uniprot','Uniprot ID'),('ipi','International Protein Index'),
                ('hprd','Human Protein Reference Database id'),('enspep','Ensembl peptide ID'), 
    ('hinvdb','H-Invitational Database'), ('ccds','conserved CDS id'),('vegag','Vega gene id'),('vegap','Vega protein id') ]
    se=forms.ChoiceField(label="Search", choices=se_options,required=False)
    seterm=forms.CharField(label="for", required=False)

def searchhumap(request):
    if request.method == 'GET':
        f = humapform(request.GET)
        objs=[]
        if not f.is_valid():
           return render_to_response('humap.html', {'form': f, 'objs': objs}) #do sth else 
        else:
           if f.cleaned_data["seterm"]:
              if f.cleaned_data["se"]=='entrez':
                 objs = Humap.objects.filter(entrezid=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='name':
                    qset = (
                      Q(name=f.cleaned_data["seterm"]) |
                      Q(synonym__icontains=f.cleaned_data["seterm"]) 
                    )
                    objs = Humap.objects.filter(qset).distinct()
              elif f.cleaned_data["se"]=='hgnc':
                  objs = Humap.objects.filter(hgnc=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='ensembl':
                  objs = Humap.objects.filter(ensembl__icontains=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='omim':
                  objs = Humap.objects.filter(omim__icontains=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='unigene':
                  objs = Humap.objects.filter(unigene=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='gi':
                  objs = Humap.objects.filter(gi__icontains=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='uniprot':
                   qset = (
                      Q(swprot__icontains=f.cleaned_data["seterm"]) |
                      Q(trembl__icontains=f.cleaned_data["seterm"]) 
                   )
                   objs = Humap.objects.filter(qset).distinct()
              elif f.cleaned_data["se"]=='ipi':
                  objs = Humap.objects.filter(ipi__icontains=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='hprd':
                  objs = Humap.objects.filter(hprd__icontains=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='enspep':
                  objs = Humap.objects.filter(enspep__icontains=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='hinvdb':
                  objs = Humap.objects.filter(hinvdb__icontains=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='ccds':
                  objs = Humap.objects.filter(ccds__icontains=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='vegag':
                  objs = Humap.objects.filter(vegag__icontains=f.cleaned_data["seterm"]).distinct()
              elif f.cleaned_data["se"]=='vegap':
                  objs = Humap.objects.filter(vegap__icontains=f.cleaned_data["seterm"]).distinct()
              return render_to_response('humap.html', {'form': f, 'objs': objs})
           else:
              return render_to_response('humap.html', {'form': f, 'objs': objs})
    else:
        f = humapform()
        return render_to_response('humap.html', {'form': f, 'objs': objs})

def stana(request):
   paths=Pathway.objects.all()
   locs= Location.objects.all()
   s=[]
   for p in paths:
      objsp = Reaction.objects.filter(pathway__exact=p)
      n=objsp.count()
      x=[p.name,n]
      for l in locs:
         objs = objsp.filter(rea_gene__gene__geneloc__loc__exact=l).distinct()
         n=objs.count()
         x.append(n)
      s.append(x)   
#         s=s+' '+str(n)
#      s=s+'\n'
   return render_to_response('sta.html', locals())
#   response=HttpResponse(s, mimetype="text/plain")
#   response['Content-Disposition']='attachment; filename=1.txt'
#   return response
    
def search(request): #without pathway selection and didnot use newforms
    query = request.GET.get('q', '')
    if query:
        qset = (
            Q(reactionid__icontains=query) |
            Q(rea_gene__gene__name__icontains=query) |
            Q(equation__icontains=query) |
            Q(eq_in_id__icontains=query) |
            Q(rea_ec__enzyme=query)
        )
        results = Reaction.objects.filter(qset).distinct()
    else:
        results = []
    return render_to_response("search.html", {
        "results": results,
        "query": query #send the results and the variable "query" back to the form 
    })

def add_rea(request):
    ReactionForm = forms.form_for_model(Reaction)
    if request.method == 'POST':
        form = ReactionForm(request.POST)
        if form.is_valid():
            form.save() #automatically update the data
            return HttpResponseRedirect('/reaction/thanks/')
    else:
        form = ReactionForm()
    return render_to_response('add_reaction.html', {'form': form})

def metgraph(request):
#    reas=request.session['r']
    metlinks=Met_linklocation.objects.filter(rea__in=reas)
    metlinks=Met_linklocation.objects.all()
    G=nx.MultiDiGraph()
    for ml in metlinks:
        rev=ml.reversibility
        G.add_edge(ml.com1.compoundid,ml.com2.compoundid,lable=ml.rea.reactionid)
        if not rev:
          G.add_edge(ml.com2.compoundid,ml.com1.compoundid,lable=ml.rea.reactionid)
#    nmet=G.number_of_nodes()
#    nlink=G.size()
#    al=nx.average_shortest_path_length(G)
#    UG=G.to_undirected()
 #   cluster=nx.average_clustering(UG) #not for mutiple graph
#    con=nx.is_connected(UG)
    request.session['mgraph']=G
#    request.session['mgraphdot']=Gd
    return render_to_response('kmetlink.html', locals())

class pathform(forms.Form): #search shortest paths
    com1=forms.CharField(label="source compound", required=False)
    com2=forms.CharField(label="target compound", required=False)

def shortpath(request): #avoid repeat reaction using breadth first search, paths as list of edges with rea data
#    from django.core.exceptions import ObjectDoesNotExist
#    fps2=open("c:/human/media/ps2.txt","w") for debuging
    if request.method == 'GET':
      f = pathform(request.GET)
      if not f.is_valid():
           err="sth wrong"
           return render_to_response('kpath1.html', locals()) #do sth else 
      else:
        c1id=f.cleaned_data["com1"]
        c2id=f.cleaned_data["com2"]
        if 'mgraph' in request.session:
           G=request.session['mgraph']
        else:   
          metlinks=Met_linklocation.objects.all()
          G=nx.MultiDiGraph()
          for ml in metlinks:
            rev=ml.reversibility
#            id1=ml.com1.compoundid
#            id2=ml.com2.compoundid
            G.add_edge(ml.com1.compoundid,ml.com2.compoundid,lable=ml.rea.reactionid)
            if rev=="T":
              G.add_edge(ml.com2.compoundid,ml.com1.compoundid,lable=ml.rea.reactionid)
          request.session['mgraph']=G
        flag=0
        paths=[]
        if c1id in G and c2id in G:
            ns=[c1id]+G.neighbors(c1id)
            if c2id in ns:
              rs=G.get_edge_data(c1id,c2id).values()
              for r in rs:
                path=[[c1id,c2id,r['lable']]]
                paths.append(path)
            else:    
              ps=G.out_edges(c1id,data=True) #just use ps
              ps2=[] #for the searched paths
              for p in ps:
                ps2.append([[p[0],p[1],p[2]['lable']]])  #change from a list of turple to a list of list
              while flag==0: #stop after find a path to c2, may be two or more paths
                newnodes=[] #for new nodes from all the existing nodes, while "newns" for new nodes from a specific node
                newps=[] #new paths to be found
                for p in ps2:
#                  newns=G.neighbors(p[-1][1])
#                  newnodes=newnodes+newns
                  newedges=G.out_edges(p[-1][1],data=True)
                  if newedges: #possible no out links
                    for ne in newedges:
                      r=ne[2].values()[0]
                      if not r==p[-1][2]:
                        if ne[1]==c2id:
                          path=p+[[ne[0],ne[1],r]] #list of list
                          paths.append(path)
                          flag=1
                        elif not ne[1] in ns: #neighbours may include nodes already found (loop)
                          newp=p+[[ne[0],ne[1],r]] #list of list
                          newps.append(newp)
                          if not ne[1] in newnodes:
                            newnodes.append(ne[1])
#                  if c2id in newns: #need to check, as maybe target in newns but not change flag as repeat rea. just do a through search
#                      rs=G.get_edge_data(p[-1][1],c2id).values()
#                      for r in rs:
#                        if not r['lable']==p[-1][2]:
#                          flag=1
#                          path=p+[[p[-1][1],c2id,r['lable']]] #list of list
#                          paths.append(path)
#                  else:
                ps2=newps
#                fps2.write(str(ps2)+"\n")
                ns=ns+newnodes #change ns after searching for all nodes to find multiple shortest paths 
            Gd=pydot.Dot()
#            fps2.close()
            edges=[] #to avoid repeat edges
            nodes=[]
            for p in paths: #should keep rea info in paths, then will not need to search metlink again.
              for e in p:
                if not e in edges:
                  edges.append(e)
                  rea=Realocation.objects.get(reactionid=e[2])
                  edot=pydot.Edge(e[0],e[1],label=e[2])
#                  edot=pydot.Edge(e[0],e[1],label=e[2],tooltip=rea.eq_in_id,labeltooltip=rea.equation)
                  edot.set_URL("/reaction/"+e[2][:6])
                  edot.set_tooltip(rea.equation)
                  Gd.add_edge(edot)
                  if not e[0] in nodes:
                    nodes.append(e[0]) 
                    node=pydot.Node(e[0])
                    node.set_URL("/compound/"+e[0][:6])
                    node.set_tooltip(e[0])
                    cname=Complocation.objects.get(compoundid=e[0]).name
                    node.set_label(cname)
#                    node.set_tooltip(cname)
                    Gd.add_node(node)
#            nodes.append(c2id) 
            node=pydot.Node(c2id)
            node.set_URL("/compound/"+c2id[:6])
            node.set_tooltip(c2id)
            cname=Complocation.objects.get(compoundid=c2id).name
            node.set_label(cname)
#            node.set_tooltip(cname)
            Gd.add_node(node)
            Gd.write(MEDIA_ROOT+'path.png', prog="dot",format="png")
            Gd.write(MEDIA_ROOT+'path.svg', prog="dot",format="svg")
            image=open(MEDIA_ROOT+'path.svg',"rb").read()
            return HttpResponse(image, mimetype="image/svg+xml")
        else:
#            a=c11id
            err="the compounds are not in the network"
            return render_to_response('kpath1.html', locals())

def shortpathold(request): #search shortest paths just use networkx
    from django.core.exceptions import ObjectDoesNotExist
    if request.method == 'GET':
      f = pathform(request.GET)
      if not f.is_valid():
           err="sth wrong"
           return render_to_response('kpath.html', locals()) #do sth else 
      else:
        c1id=f.cleaned_data["com1"]
        c2id=f.cleaned_data["com2"]
#        try:
#          c1=Complocation.objects.get(compoundid=c1id)
#          c2=Complocation.objects.get(compoundid=c2id)
#        except ObjectDoesNotExist:
#          err="can not find the compound, check your id"
#          return render_to_response('kpath.html', locals())
#        c1nm=c1.name #when the networkx graph use name rather than IDs
#        c2nm=c2.name
        if 'mgraph' in request.session:
          G=request.session['mgraph']
        else:   
          metlinks=Met_linklocation.objects.all()
          G=nx.MultiDiGraph()
          for ml in metlinks:
            rev=ml.reversibility
#          id=ml.id1
#          id1=ml.com1.compoundid
#          id2=ml.com2.compoundid
            G.add_edge(ml.com1.compoundid,ml.com2.compoundid,lable=ml.rea.reactionid)
            c=rr
            if rev=="T":
              G.add_edge(ml.com2.compoundid,ml.com1.compoundid,lable=ml.rea.reactionid)
          request.session['mgraph']=G
#        if c1nm in ns and c2nm in ns:
        nlink=G.size()
        if c1id in G and c2id in G:
            Gd=pydot.Dot()
            p=nx.shortest_path(G,c1id,c2id)
#            cn[0]=Complocation.objects.get(compoundid=p[0]).name
            for i in range(len(p)-1):
#               G[p[i]][p[i+1]]['lable']
#                 cn[i+1]=Complocation.objects.get(compoundid=p[i+1]).name
#                 e=pydot.Edge(cn[i],cn[i+1])
#                 e.set_label(link.rea.reactionid)
#                 e.set_URL("/kegg/rn/"+link.rea.reactionid)
#                 Gd.add_edge(e)
               metlinks=Met_linklocation.objects.filter(com1=p[i]).filter(com2=p[i+1])
               cn=Complocation.objects.get(compoundid=p[i]).name
               n=pydot.Node(cn)
#               n.set_URL("/kegg/cpd/"+p[i])
               n.set_tooltip(p[i])
               Gd.add_node(n)
               for link in metlinks:
#                 e=pydot.Edge(link.com1.name,link.com2.name)
                 e=pydot.Edge(link.com1.name,link.com2.name)
                 e.set_label(link.rea.reactionid)
#                 e.set_URL("/kegg/rn/"+link.rea.reactionid)
                 e.set_tooltip(link.rea.equation)
                 Gd.add_edge(e)
               metlinks=Met_linklocation.objects.filter(com2=p[i]).filter(com1=p[i+1]) #for reversible links
               for link in metlinks:
#                 e=pydot.Edge(link.com1.name,link.com2.name)
                 if link.rea.reversibility=="T":
                   e=pydot.Edge(link.com2.name,link.com1.name)
                   e.set_label(link.rea.reactionid)
#                   e.set_URL("/kegg/rn/"+link.rea.reactionid)
                   e.set_tooltip(link.rea.equation)
                   Gd.add_edge(e)
            cn=Complocation.objects.get(compoundid=p[-1]).name
            n=pydot.Node(cn) #the last one
#            n.set_URL("/kegg/cpd/"+p[-1])
            n.set_tooltip(p[-1])
            Gd.add_node(n)
            Gd.write(MEDIA_ROOT+'path.svg', prog="dot",format="svg")
            image=open(MEDIA_ROOT+'path.svg',"rb").read()
            return HttpResponse(image, mimetype="image/svg+xml")
        else:
            err="the compounds are not in the network"
            return render_to_response('kpath.html', locals())

class netviewform(forms.Form):
    foptions=[('svg','svg'),('png','png'),('gif','gif'),('jpg','jpg')]
#    foptions=[('jpg','jpg'),('png','png'),('gif','gif'),('bmp','bmp'),('svg','svg'),
#              ('dot','dot'),('eps','eps'),('ps','ps'),('pdf','pdf')]
    poptions=[('dot','dot'),('neato','neato'),('twopi','twopi'),('fdp','fdp')]
    fformat=forms.ChoiceField(label="format", choices=foptions,required=False)
    prog=forms.ChoiceField(label="program", choices=poptions,required=False)
    rlabel=forms.BooleanField(label="reaction label",required=False)
    mlabel=forms.BooleanField(label="metabolite label",required=False)
    size=forms.CharField(label="node size", help_text='0.02 to 0.5. or type 1 to fit node label', required=False)

def mgraphvisnew(request): #try to generate network picture without lables,
    #only works for small network now. Why take very long time to generate a layout
    #without lable but very fast for a graph with lable.
#    import pydot
    reas=request.session['ehmnr']
    metlinks=Met_link.objects.filter(rea__in=reas)
#    Gd = pydot.Dot(graph_type='digraph')
    G = pydot.Dot()
    G.set_concentrate("true")
    if request.method == 'GET':
        f = netviewform(request.GET)
        if not f.is_valid():
           return render_to_response('dotviewk.html', {'form': f}) #do sth else 
        else:
#           f.cleaned_data["rlabel"]="T" #to be commented to show graph without lables
#           f.cleaned_data["mlabel"]="T"
           if f.cleaned_data["fformat"]:
              fformat=f.cleaned_data["fformat"]
           else:   
              fformat='svg'
           if f.cleaned_data["prog"]:
              prog=f.cleaned_data["prog"]
           else:   
              prog='dot'
           for link in metlinks:
              e=pydot.Edge(link.com1.name,link.com2.name, URL="/reaction/"+link.rea.reactionid, tooltip=link.rea.equation,target='_blank')
              if f.cleaned_data["rlabel"]:
                 e.set_label(link.rea.reactionid)
                 e.set_labeltooltip(link.rea.eq_in_id)
              e.set_arrowsize("0.2")
              G.add_edge(e)
              if f.cleaned_data["mlabel"]:
                n1=pydot.Node(link.com1.name, URL="/compound/"+link.com1.compoundid,target='_blank')
                n2=pydot.Node(link.com2.name, URL="/compound/"+link.com2.compoundid,target='_blank')
              else:  
                if f.cleaned_data["size"]:
                  size=f.cleaned_data["size"]
                else:   
                  size="0.05"
                n1=pydot.Node(link.com1.name, fixedsize="1", height=size,width=size,URL="/kegg/cpd/"+link.com1.compoundid,target='_blank')
                n2=pydot.Node(link.com2.name, fixedsize="1", height=size,width=size,URL="/kegg/cpd/"+link.com2.compoundid,target='_blank')
                n1.set_label("") #try this first
                n2.set_label("") #try this first
                n1.set_tooltip(link.com1.name) #try this first
                n2.set_tooltip(link.com2.name) #try this first
              G.add_node(n1)
              G.add_node(n2)
           G.write(MEDIA_ROOT+'mg'+prog+'.'+fformat, prog=prog,format=fformat)
#           if fformat=='svg':
#              image=open('c:/human/media/mg'+prog+'.svg',"rb").read()
#              return HttpResponse(image, mimetype="image/svg+xml")
#           else: 
           return render_to_response("kdotviewnew.html", {'form': f,'prog':prog,'format': fformat})

def saveehmnsbml(request):
      ehmn=open(MEDIA_ROOT+'ehmn.sbml',"rb").read()
      response=HttpResponse(ehmn, mimetype="text/xml")
      response['Content-Disposition']='attachment; filename=ehmn.xml'
      return response
